package rhc.taskSchedule.taskSchedule.task.manage;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import rhc.discribute.node.host.Host;
import rhc.taskSchedule.commander.TaskScheduleCommanderExecute;
import rhc.taskSchedule.entity.RunningStatus;
import rhc.taskSchedule.entity.TaskType;
import rhc.taskSchedule.exception.RunningException;
import rhc.taskSchedule.taskSchedule.BasicManage;
import rhc.taskSchedule.taskSchedule.task.TaskExecute;
import rhc.taskSchedule.taskSchedule.task.TaskExecuteManage;
import rhc.taskSchedule.taskSchedule.task.execute.TaskExecuteImpl;
import rhc.taskSchedule.taskSignalCall.CallCustom;
import rhc.taskSchedule.taskSignalCall.CustomCall;
import rhc.taskSchedule.taskSignalCall.NoticeCustom;
import rhc.taskSchedule.taskSignalCall.impl.CustomCallImpl;

abstract public class BasicTaskExecuteManageImpl extends BasicManage implements TaskExecuteManage {

	/**
	 * 任务分发器
	 */
	protected TaskScheduleCommanderExecute taskScheduleCommanderExecute;
	
	/**
	 * 运行id对应的任务执行器
	 */
	protected Map<String,TaskExecute> runningId_taskExcecute=new HashMap<String,TaskExecute>();
	
	/**
	 * 源id对应的运行id列表，一个任务或调度可能多次运行，也可能在同一个机器上多次运行
	 */
	protected Map<String,List<String>> sourceId_runningIdList=new HashMap<String,List<String>>();
	
	/**
	 * 运行id对应的通知客户系统的调用
	 */
	protected Map<String,CallCustom> runningId_callCustom=new HashMap<String,CallCustom>();
	
	/**
	 * 客户系统注册的主动调用
	 */
	protected Map<String,List<NoticeCustom>> taskTypeName_noticeCustomList;
	
	protected Host currentHost;

	public BasicTaskExecuteManageImpl(TaskScheduleCommanderExecute taskScheduleCommanderExecute) throws Exception{
		this.taskScheduleCommanderExecute=taskScheduleCommanderExecute;
		currentHost=taskScheduleCommanderExecute.getDistributeNodeCommander().getNodeManage().getCurrentHost();
	}
	
	@Override
	public RunningStatus getRunStatus(String runningId) throws Exception {
		TaskExecute taskExecute=getTaskExecuteByRunningId(runningId);
		
		return taskExecute.getRunStatus();
	}

	@Override
	public void createRunning(String runningId) throws Exception {
		if(runningId_taskExcecute.containsKey(runningId)){
			throw new RunningException("运行 {} 已存在",runningId);
		}
		TaskExecute taskExecute=new TaskExecuteImpl(runningId,currentHost);
		TaskType taskType=taskExecute.getTaskType();
		String taskTypeName=taskType.getTaskTypeName();
		
		List<NoticeCustom> noticeCustomList=taskTypeName_noticeCustomList.get(taskTypeName);
		String taskId=taskExecute.getSourceId();
		Exception exception=null;
		try{
			if(null != noticeCustomList && !noticeCustomList.isEmpty()){
				for(NoticeCustom noticeCustom:noticeCustomList){
					CustomCall customCall=new CustomCallImpl(taskExecute);
					noticeCustom.noticeCustom(runningId, taskId, taskType, customCall, this);
				}
			}
		}catch(Exception e){
			exception=e;
		}finally{
			if(null == exception){
				//没出错
				runningId_taskExcecute.put(runningId, taskExecute);
				
				List<String> runningIdList=sourceId_runningIdList.get(runningId);
				if(null == runningIdList){
					runningIdList=new LinkedList<String>();
					sourceId_runningIdList.put(taskId, runningIdList);
				}
				runningIdList.add(runningId);
			}else{
				taskExecute.error();
				throw exception;
			}
		}
		
	}
	
	@Override
	public TaskExecute getTaskExecuteByRunningId(String runningId) throws Exception {
		TaskExecute taskExecute=runningIdExists(runningId,true)?runningId_taskExcecute.get(runningId):null;
		
		return taskExecute;
	}
	
	@Override
	public List<String> getAllRunningId() throws Exception {
		return new LinkedList<String>(runningId_taskExcecute.keySet());
	}
	
	@Override
	public void registerNoticeCustom(String taskTypeName,NoticeCustom noticeCustom) throws Exception{
		List<NoticeCustom> noticeCustomList=null;
		if(null == (noticeCustomList=taskTypeName_noticeCustomList.get(taskTypeName))){
			noticeCustomList=new LinkedList<NoticeCustom>();
			taskTypeName_noticeCustomList.put(taskTypeName, noticeCustomList);
		}
		noticeCustomList.add(noticeCustom);
	}
	
	@Override
	public void registerCallCustom(String runningId,CallCustom callCustom) throws Exception{
		runningId_callCustom.put(runningId, callCustom);
	}
	
	/**根据runningId获取客户注册的回调
	 * @param runningId
	 * @return
	 */
	protected CallCustom getCallCustomByRunningId(String runningId){
		return runningId_callCustom.get(runningId);
	}
	
	/**运行id是否存在
	 * @param runningId
	 * @return
	 */
	protected boolean runningIdExists(String runningId,boolean throwsException) throws Exception{
		TaskExecute taskExecute=runningId_taskExcecute.get(runningId);
		if(null == taskExecute && throwsException){
			throw new RunningException("运行 {} 在内存中不存在，可能已停止或未启动",runningId);
		}
		return null != taskExecute;
	}

}
